//
//  NXTPadController.m
//
//  Created by Jean-Luc Béchennec on 18/03/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "NXTPadController.h"

@implementation NXTPadController
/***/
// asuivre http://stackoverflow.com/questions/4639379/how-to-use-nstrackingarea
	

//WII 
- (IBAction)wiiConnect:(id)sender{
	boutonisPressed = true;
	NSLog(@" WII detect");
	discovery = [[WiiRemoteDiscovery alloc] init];
	[discovery setDelegate:self];
	[discovery start];

}
#pragma mark -
#pragma mark WiiRemoteDiscovery delegates
- (void) accelerationChanged:(WiiAccelerationSensorType)type accX:(unsigned short)accX accY:(unsigned short)accY accZ:(unsigned short)accZ{
}
- (void) wiiRemoteDisconnected:(IOBluetoothDevice*)device {
	
	NSLog(@"\n===== lost connection with WiiRemote =====");
}
- (void) buttonChanged:(WiiButtonType)type isPressed:(BOOL)isPressed{

	//NSLog(@"\n===== Presse BTN =====");
	if (type == WiiRemoteAButton){
		NSLog(@"\n===== Presse A =====");
		if (boutonisPressed)[self pushBall:self];
		boutonisPressed = !boutonisPressed ;

	}
	else if (type == WiiRemoteBButton){
		NSLog(@"\n===== Presse B =====");
		[self stopMove:self];
		
	}
	else if (type == WiiRemoteUpButton){
		NSLog(@"\n===== Presse Left =====");
		
		if (boutonisPressed) [self turnLeft:self];
			else [self stopMove:self];
		
		boutonisPressed = !boutonisPressed ;


	}
	else if (type == WiiRemoteDownButton){
		NSLog(@"\n===== Presse Right =====");
		if (boutonisPressed) [self turnRight:self];
			else [self stopMove:self];
		boutonisPressed = !boutonisPressed ;


	}
	else if (type == WiiRemoteHomeButton){
		NSLog(@"\n===== Presse Home =====");
		if (boutonisPressed)[self Connect];
		boutonisPressed = !boutonisPressed ;

	}
	/*else{
		NSLog(@"\n=====  release");
		}
*/


}
- (void) WiiRemoteDiscoveryError:(int)code {
	//[discoverySpinner stopAnimation:self];
	NSLog(@"\n===== WiiRemoteDiscovery error.  If clicking Find Wiimote gives this error, try System Preferences > Bluetooth > Devices, delete Nintendo. (%d) =====", code);
}

- (void) willStartWiimoteConnections {
	NSLog(@"\n===== WiiRemote discovered.  Opening connection. =====");
}

- (void) WiiRemoteDiscovered:(WiiRemote*)wiimote {
	
	//	[discovery stop];
	
	// the wiimote must be retained because the discovery provides us with an autoreleased object
	
	[wiimote setDelegate:self];
	
	NSLog(@"\n===== Connected to WiiRemote ===== %@", wiimote);
	//[discoverySpinner stopAnimation:self];
	
	[wiimote setLEDEnabled1:YES enabled2:NO enabled3:YES enabled4:NO];
	//[wiimoteQCView setValue:[NSNumber numberWithBool:[led1 state] ] forInputKey:[NSString stringWithString:@"LED_1"]];
	
	[wiimote setMotionSensorEnabled:YES];
	//	[wiimote setIRSensorEnabled:YES];
	
	//[graphView startTimer];
	//[graphView2 startTimer];
	
	//NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
	//[mappingController setSelectionIndex:[[defaults objectForKey:@"selection"] intValue]];
}
//End WII

- (void) viewWillMoveToWindow:(NSWindow *)newWindow {
    // Setup a new tracking area when the view is added to the window.
    //NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect: options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways) owner:self userInfo:nil];
  //  [self addTrackingArea:trackingArea];
}

- (void) mouseEntered:(NSEvent*)theEvent {
    // Mouse entered tracking area.
}

- (void) mouseExited:(NSEvent*)theEvent {
    // Mouse exited tracking area.
}
//***/

- (void)sendMessage:(void*)message length:(UInt8)length
{
    char fullMessage[66]; // maximum message size (64) + size (2)
    
    fullMessage[0] = length;
    fullMessage[1] = 0;
    memcpy(fullMessage+2, message, length);
    
    
    //[self dumpMessage:fullMessage length:length+2 prefix:@"-> "];
    [mRFCOMMChannel writeSync:fullMessage length:length+2];
}
- (void)sendCommand:(char) c1{
					 //v1:(char) c2{
	cmd[0] = 3; //LSB de taille 
	cmd[1] = 0x00; //MSB fde taille 
	cmd[2] = c1;
	cmd[3] = 0x00;
	cmd[4] = 0x20; // Joke
	if ( IOBluetoothRFCOMMChannelWrite(rfcommChannel,cmd,5,cmd[80]) ==0 )
	//if (IOBluetoothRFCOMMChannelWriteSync(rfcommChannel,cmd,1 )) //Error si marche pas 
	//if (IOBluetoothRFCOMMChannelWriteSync(rfcommChannel,cmd,2)) //Error si marche pas 
	//while(!(IOBluetoothRFCOMMChannelWriteAsync(rfcommChannel,cmd,2,0 ))){
	///	while(!(IOBluetoothRFCOMMChannelWriteAsync(rfcommChannel,cmd,2,0 )));
	{ 
		printf("Successfully sent command! %d %d\n", cmd[2]);
	}
	else
	{
		fprintf(stderr,"IOBluetoothRFCOMMChannelWrite() failed.\n");
	}
	//IOBluetoothRFCOMMChannelWriteSimple(<#IOBluetoothRFCOMMChannelRef rfcommChannel#>, <#void * data#>, <#UInt16 length#>, <#Boolean sleepFlag#>, <#UInt32 * numBytesSent#>)
	new_data = 0;
	
}
- (IBAction)backward:(id)sender {
  NSLog(@"On freine !\n");
	//[self sendCommand:0x02];
	
}

- (IBAction)forward:(id)sender {
  NSLog(@"En avant !\n");

	

}
- (IBAction)turnLeft:(id)sender {
	
	//[sender setTitle:[NSString stringWithFormat:@"%d",position--]];

	//	[self sendCommand:0x03];
	
	NSLog(@"À gauche !\n");

	//[self sendCommand:0x01];
	char message[] = {
        0x02,
		0x02,
		0x02,
		
    };
	/*if (leftPredState == [sender state] ) {
		message[0]=0x2;
		message[1]=0x2;
		message[2]=0x2;
    }
	else{
		NSLog(@"STOP!\n");
		
	}*/
    
    // send the message
    [self sendMessage:message length:3];
}
- (IBAction)pushBall:(id)sender {
	NSLog(@"Ball !\n");
	
	//[self sendCommand:0x01];
	char message[] = {
        0x08,
		0x08,
		0x08,
		
    };
	
    [self sendMessage:message length:3];
}
- (IBAction)stopMove:(id)sender {
	
	//[sender setTitle:[NSString stringWithFormat:@"%d",position--]];
	
	//	[self sendCommand:0x03];
	
	NSLog(@"STOP !\n");
	
	//[self sendCommand:0x01];
	char message[] = {
        0x0,
		0x0,
		0x0,
		
    };

    [self sendMessage:message length:3];
}
- (IBAction)goTo:(id)sender {
	NSLog(@" DISTANCE");
	[(NSTextField *) affichageDistance setStringValue:[(NSTextField *) Distance stringValue]];
	char message[] = {
        0x1,
		0x1,
		0x0
		
    };
    message [2]= [[(NSTextField *) Distance stringValue] intValue];
	//message [1]= [[(NSTextField *) Distance stringValue] intValue];

    // send the message
    [self sendMessage:message length:3];
	
}

- (IBAction)turnRight:(id)sender {
	

	
	//[sender setTitle:[NSString stringWithFormat:@"%d",position++]];
    NSLog(@"À droite !  \n");
	//	[self sendCommand:0x04];
	char message[] = {
        0x04,
		0x04,
		0x04,
		
    };
	//if (rightPredState == [sender state] ) {
		/*message[0]=0x4;
		message[1]=0x4;
		message[2]=0x4;

	/*}
	else{
		NSLog(@"STOP!\n");

	}*/
    // send the message
    [self sendMessage:message length:3];
}

- (IBAction)toggleConnect:(id)sender {
	connectionState = [sender state];
	NSArray *padButtons = [[padBox contentView] subviews];
	if (connectionState) {
		NSLog(@"Bouton Enfoncé\n");
	}
	else {
		NSLog(@"Bouton Relâché\n");
	}
	
	NSEnumerator *en = [padButtons objectEnumerator];
	id button;
	while (button = [en nextObject]) {
		NSLog(@"bouton\n");
		//[button setEnabled:connectionState];
		[button setEnabled:TRUE];
	}
	
	
	[self Connect];
}
- (BOOL)Connect {
	NSLog (@"DEM cONNECT ");
	IOBluetoothDeviceSelectorController *deviceSelector;
	IOBluetoothSDPUUID                                      *sppServiceUUID;
	NSArray                                                         *deviceArray;
	
    NSLog( @"Attempting to connect" );
   // [self setDelegate:self];
	// The device selector will provide UI to the end user to find a remote device
    deviceSelector = [IOBluetoothDeviceSelectorController deviceSelector];
	//[deviceSelector runModal];
	if ( deviceSelector == nil ) {
		NSLog( @"Error - unable to allocate IOBluetoothDeviceSelectorController.\n" );
		return FALSE;
	}
	sppServiceUUID = [IOBluetoothSDPUUID uuid16:kBluetoothSDPUUID16ServiceClassSerialPort];
	[deviceSelector addAllowedUUID:sppServiceUUID];
	if ( [deviceSelector runModal] != kIOBluetoothUISuccess ) {
		NSLog( @"User has cancelled the device selection.\n" );
		return FALSE;
	}       
	deviceArray = [deviceSelector getResults];      
	if ( ( deviceArray == nil ) || ( [deviceArray count] == 0 ) ) {
		NSLog( @"Error - no selected device.  ***This should never happen.***\n" );
		return FALSE;
	}
	IOBluetoothDevice *device = [deviceArray objectAtIndex:0];
	IOBluetoothSDPServiceRecord     *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID];
	if ( sppServiceRecord == nil ) {
		NSLog( @"Error - no spp service in selected device.  ***This should never happen since the selector forces the user to select only devices with spp.***\n" );
		return FALSE;
	}
	// To connect we need a device to connect and an RFCOMM channel ID to open on the device:
	UInt8   rfcommChannelID;
	if ( [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID] != kIOReturnSuccess ) {
		NSLog( @"Error - no spp service in selected device.  ***This should never happen an spp service must have an rfcomm channel id.***\n" );
		return FALSE;
	}
	
	// Open asyncronously the rfcomm channel when all the open sequence is completed my implementation of "rfcommChannelOpenComplete:" will be called.
	if ( ( [device openRFCOMMChannelAsync:&mRFCOMMChannel withChannelID:rfcommChannelID delegate:self] != kIOReturnSuccess ) && ( mRFCOMMChannel != nil ) ) {
		// Something went bad (looking at the error codes I can also say what, but for the moment let's not dwell on
		// those details). If the device connection is left open close it and return an error:
		NSLog( @"Error - open sequence failed.***\n" );
		//[self close:device];
		return FALSE;
	}
	
	mBluetoothDevice = device;
	[mBluetoothDevice  retain];
	[mRFCOMMChannel retain];
	
	//Listener SELF
		//
	[mRFCOMMChannel setDelegate:self];
	[deviceSelector close];
	return TRUE;
}



- (IBAction)toggleConnectold:(id)sender {
  connectionState = [sender state];
  NSArray *padButtons = [[padBox contentView] subviews];
  if (connectionState) {
    NSLog(@"Bouton Enfoncé\n");
  }
  else {
    NSLog(@"Bouton Relâché\n");
  }

  NSEnumerator *en = [padButtons objectEnumerator];
  id button;
  while (button = [en nextObject]) {
    NSLog(@"bouton\n");
    //[button setEnabled:connectionState];
	  [button setEnabled:TRUE];
  }
	
	//[button setEnabled:TRUE];
	//TEST
	IOBluetoothDeviceSelectorController *deviceSelector;
	NSArray *deviceArray;
	deviceSelector = [IOBluetoothDeviceSelectorController
					  deviceSelector];
	[deviceSelector runModal];
	deviceArray = [deviceSelector getResults];
	btDevice= [deviceArray objectAtIndex:0];
	NSLog (@" OBJECT : %@",deviceArray);
	NSLog(@"--%@",[btDevice getNameOrAddress])	;
	
	NSLog(@"--%@",IOBluetoothDeviceGetName(btDevice));
	NSLog(@"--%X",IOBluetoothDeviceGetAddress(btDevice));
	//
	//CHECK BLUETOOTH COM
	if
		( IOBluetoothDeviceRemoteNameRequest(btDevice,NULL,NULL,btName) !=
		 kIOReturnSuccess )
	{
		fprintf(stderr,"IOBluetoothDeviceRemoteNameRequest() failed.\n");
		return 1;
	}
	else
	{
		name = IOBluetoothDeviceGetName(btDevice);
		printf("CFString name = %p\n",name);
		if ( CFStringGetCString(name,raw_name,
								100,kCFStringEncodingISOLatin1) )
			printf("Device name = %s\n",raw_name);
		else
			fprintf(stderr,"CFStringGetCString() failed.\n");
	}
	/* Open an RFCOMM channel to the NXT.  The underlying baseband
	 connection is automatically opened if needed.  The process
	 isn't finished until a listener callback function is
	 registered,
	 since synchronous reads are not supported. */
	if
		( IOBluetoothDeviceOpenRFCOMMChannel(btDevice,NXT_RFCOMM_CHANNEL_ID,
											 &rfcommChannel) != kIOReturnSuccess )
	{
		fprintf(stderr,"IOBluetoothDeviceOpenRFCOMMChannel() failed.\n");
		return 1;
	}
	else
	{
		printf("Successfully opened RFCOMM channel!\n");
	}
	
	/* Check Max Transmission unit, just for kicks. */
	printf("MTU = %d\n",IOBluetoothRFCOMMChannelGetMTU(rfcommChannel));
	
	
	if ( IOBluetoothRFCOMMChannelRegisterIncomingDataListener(rfcommChannel,listener,&new_data) == 0 )
	{
		/* Get battery level */
		cmd[0] = 0x00;
		cmd[1] = 0x0B;
		new_data = 0;   /* Make use of the refCon arg by setting a
		 flag. */
		[self sendCommand:0x00];
	
	}
	else
	{
		
		fprintf(stderr,"IOBluetoothRFCOMMChannelRegisterIncomingDataListener()failed.\n");
	}
	
	
	
}
/**
 COMM BLUETOOTH TEST READ 
 */
void    listener(IOBluetoothRFCOMMChannelRef rfcommChannel, void *data, UInt16 length, void *refCon)
{
	int     c,
	*new_data = refCon;
	
	puts("Got data!");
	for (c=0; c<length; ++c)
	printf("%02X ",((char *)data)[c]);
	putchar('\n');
	*new_data = 1;
	//CFRunLoopStop(CFRunLoopGetCurrent());
}
/**
 */

- (void)awakeFromNib {
  connectionState = 0;
	position = 0;
}


///TEST 


- (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel *)rfcommChannel
{
	
}

- (void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel status:(IOReturn)error
{
       
	
}

- (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength
{
	NSString *hexMessage = [NSString string];
    int i;
	//NSLog(@" DATA1 %d ---> %d,%d,%.2p,%.2p,%.2p,%.2p, ", dataLength,*((unsigned char *)dataPointer),*((unsigned char *)dataPointer+1),*((unsigned char *)dataPointer+2),*((unsigned char *)dataPointer+3),*((unsigned char *)dataPointer+4),*((unsigned char *)dataPointer+5));
	for (i = 0; i < dataLength; i++)
        hexMessage = [hexMessage stringByAppendingString:[NSString stringWithFormat:@"%d, ", *((unsigned char *)dataPointer+i)]];
    NSLog(@"DATA %d %@",*((char *)dataPointer+3)  ,hexMessage);

}


/// TEST WIIMOTE 
@end
